#include "CMatrixMgr.h"
#include "commclass.h"
#include "commerrno.h"
#include "../data/CPlayerOnlineData.h"
#include "../mainctrl.h"
#include "MsgMatrix.pb.h"
#include "MsgGM.pb.h"
#include "commmsg.h"
#include "CTSizeString.h"

//注册时候把主角放到对应职业限制的最后一个位置
int CMatrixMgr::InitMatrix(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail)
{
    int iRet = CMainCtrl::m_pstMain->m_stRoleMgr.CheckValidCareer(
        stPlayerBase._ucCareer);
    CT_RETURN(iRet);

    stPlayerDetail._stPlayerMatrix.Clear();

    CMatrixList stMatrixList;
    stMatrixList._uiPosMask = 0;

    stMatrixList._astMatrixList.m_iUsedCount =
        stMatrixList._astMatrixList.GetCount();
    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        //开启一个阵形的时候 必须初始化 且全量分配
        stMatrixList._astMatrixList[i].Clear();
    }

    stMatrixList._achCareerCount.m_iUsedCount =
        stMatrixList._achCareerCount.GetCount();
    for (int i = 0; i < stMatrixList._achCareerCount.Size(); ++i)
    {
        //开启一个阵形的时候 必须初始化 且全量分配
        //下标+1表示职业 数值表示该职业当前个体数
        stMatrixList._achCareerCount[i] = 0;
    }

    char chPos = 0;
    unsigned int uiPosMask = 0;
    iRet = GetDefaultIndexAndMask(stPlayerBase._ucCareer, chPos, uiPosMask);
    CT_RETURN(iRet);

    CMatrixUnit stMatrixUnit;//定义时初始化
    stMatrixUnit._chType = GAME_OBJ_TYPE_PLAYER;
    stMatrixUnit._chPos = chPos;
    stMatrixUnit._uiID = stPlayerBase._uiGID;

    stMatrixList._uiPosMask |= uiPosMask;

    stMatrixList._astMatrixList[0] = stMatrixUnit;//把主角放到第一个位置
    ++stMatrixList._achCareerCount[stPlayerBase._ucCareer - 1];

    stPlayerDetail._stPlayerMatrix._astMatrixData.AddOneItem(stMatrixList);
    stPlayerDetail._stPlayerMatrix._chMainMatrix = 0;//主阵形为下标为0的阵形

    return 0;
}

int CMatrixMgr::GetDefaultIndexAndMask(unsigned char ucCareer, char& chPos,
        unsigned int& uiPosMask)
{
    switch (ucCareer)
    {
    case CAREER_1://魔剑士
    case CAREER_4://魔斗士
        chPos = MATRIX_POS_FRONT_INDEX_C;
        uiPosMask = MATRIX_POS_FRONT_MASK_C;
        break;
    case CAREER_2://魔法师
    case CAREER_3://魔猎手
        chPos = MATRIX_POS_BACK_INDEX_F;
        uiPosMask = MATRIX_POS_BACK_MASK_F;
        break;
    default:
        return ERROR_WRONG_CAREER;
    }

    return 0;
}

int CMatrixMgr::PosMaskToIndex(unsigned int uiPosMask, int& iIndex)
{
    switch (uiPosMask)
    {
    case MATRIX_POS_FRONT_MASK_A:
        iIndex = MATRIX_POS_FRONT_INDEX_A;
        break;
    case MATRIX_POS_FRONT_MASK_B:
        iIndex = MATRIX_POS_FRONT_INDEX_B;
        break;
    case MATRIX_POS_FRONT_MASK_C:
        iIndex = MATRIX_POS_FRONT_INDEX_C;
        break;
    case MATRIX_POS_BACK_MASK_D:
        iIndex = MATRIX_POS_BACK_INDEX_D;
        break;
    case MATRIX_POS_BACK_MASK_E:
        iIndex = MATRIX_POS_BACK_INDEX_E;
        break;
    case MATRIX_POS_BACK_MASK_F:
        iIndex = MATRIX_POS_BACK_INDEX_F;
        break;
    default:
        return ERROR_MATRIX_POS_MASK_INVALID;
    }

    return 0;
}

int CMatrixMgr::GetPosNumByIndex(char chPos)
{
    switch (chPos)
    {
    case MATRIX_POS_FRONT_INDEX_C:
        return MATRIX_POS_NUMBER_F;
    case MATRIX_POS_FRONT_INDEX_B:
        return MATRIX_POS_NUMBER_E;
    case MATRIX_POS_FRONT_INDEX_A:
        return MATRIX_POS_NUMBER_D;
    case MATRIX_POS_BACK_INDEX_F:
        return MATRIX_POS_NUMBER_C;
    case MATRIX_POS_BACK_INDEX_E:
        return MATRIX_POS_NUMBER_B;
    case MATRIX_POS_BACK_INDEX_D:
        return MATRIX_POS_NUMBER_A;
    default:
        return 0;
    }
}

int CMatrixMgr::GetRtoLPosNumByIndex(char chPos)
{
    switch (chPos)
    {
    case MATRIX_POS_FRONT_INDEX_C:
        return MATRIX_POS_NUMBER_A;
    case MATRIX_POS_FRONT_INDEX_B:
        return MATRIX_POS_NUMBER_B;
    case MATRIX_POS_FRONT_INDEX_A:
        return MATRIX_POS_NUMBER_C;
    case MATRIX_POS_BACK_INDEX_F:
        return MATRIX_POS_NUMBER_D;
    case MATRIX_POS_BACK_INDEX_E:
        return MATRIX_POS_NUMBER_E;
    case MATRIX_POS_BACK_INDEX_D:
        return MATRIX_POS_NUMBER_F;
    default:
        return 0;
    }
}

char CMatrixMgr::GetIndexByPosNum(int iIndex)
{
    switch (iIndex)
    {
    case MATRIX_POS_NUMBER_F:
        return MATRIX_POS_FRONT_INDEX_C;
    case MATRIX_POS_NUMBER_E:
        return MATRIX_POS_FRONT_INDEX_B;
    case MATRIX_POS_NUMBER_D:
        return MATRIX_POS_FRONT_INDEX_A;
    case MATRIX_POS_NUMBER_C:
        return MATRIX_POS_BACK_INDEX_F;
    case MATRIX_POS_NUMBER_B:
        return MATRIX_POS_BACK_INDEX_E;
    case MATRIX_POS_NUMBER_A:
        return MATRIX_POS_BACK_INDEX_D;
    default:
        return 0;
    }
}

int CMatrixMgr::CheckMatrixObjType(char chObjType)
{
    //阵型支持的个体类型
    if (GAME_OBJ_TYPE_PLAYER != chObjType && GAME_OBJ_TYPE_PARTNER != chObjType)
    {
        return ERROR_MATRIX_UNKNOWN_OBJ_TYPE;
    }

    return 0;
}

int CMatrixMgr::GetUnitIndexByTypeAndID(CMatrixList& stMatrixList, char chType,
        unsigned int uiID)
{
    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        if (chType == stMatrixList._astMatrixList[i]._chType &&
            uiID == stMatrixList._astMatrixList[i]._uiID)
        {
            return i;
        }
    }

    return -1;
}

int CMatrixMgr::IndexToPosMask(unsigned int& uiPosMask, int iIndex)
{
    switch (iIndex)
    {
    case MATRIX_POS_FRONT_INDEX_A:
        uiPosMask = MATRIX_POS_FRONT_MASK_A;
        break;
    case MATRIX_POS_FRONT_INDEX_B:
        uiPosMask = MATRIX_POS_FRONT_MASK_B;
        break;
    case MATRIX_POS_FRONT_INDEX_C:
        uiPosMask = MATRIX_POS_FRONT_MASK_C;
        break;
    case MATRIX_POS_BACK_INDEX_D:
        uiPosMask = MATRIX_POS_BACK_MASK_D;
        break;
    case MATRIX_POS_BACK_INDEX_E:
        uiPosMask = MATRIX_POS_BACK_MASK_E;
        break;
    case MATRIX_POS_BACK_INDEX_F:
        uiPosMask = MATRIX_POS_BACK_MASK_F;
        break;
    default:
        return ERROR_MATRIX_POS_INDEX_INVALID;
    }

    return 0;
}

int CMatrixMgr::GetCareerLimit(unsigned char ucCareer, int& iCount)
{
    switch (ucCareer)
    {
    case CAREER_1://魔剑士
        iCount = MATRIX_COUNT_LIMIT_SWORD;
        break;
    case CAREER_2://魔法师
        iCount = MATRIX_COUNT_LIMIT_MAGE;
        break;
    case CAREER_3://魔猎手
        iCount = MATRIX_COUNT_LIMIT_BOW;
        break;
    case CAREER_4://魔斗士
        iCount = MATRIX_COUNT_LIMIT_GUARD;
        break;
    default:
        return ERROR_WRONG_CAREER;
    }

    return 0;
}

int CMatrixMgr::CheckCareerPos(unsigned char ucCareer, char chPos, char chObj)
{
    //策划要求暂时不对职业的站位进行限制 所以阵型中的两种个体都不需要检查
    bool bNeedCheck =
        (GAME_OBJ_TYPE_PLAYER != chObj && GAME_OBJ_TYPE_PARTNER != chObj);

    switch (ucCareer)
    {
    case CAREER_1://魔剑士
    case CAREER_4://魔斗士
        if (chPos < MATRIX_POS_FRONT_INDEX_A ||
                chPos > MATRIX_POS_FRONT_INDEX_C)
        {
            return (bNeedCheck ? ERROR_MATRIX_FRONT_POS_LIMIT : 0);
        }
        break;
    case CAREER_2://魔法师
    case CAREER_3://魔猎手
        if (chPos < MATRIX_POS_BACK_INDEX_D || chPos > MATRIX_POS_BACK_INDEX_F)
        {
            return (bNeedCheck ? ERROR_MATRIX_BACK_POS_LIMIT : 0);
        }
        break;
    default:
        return ERROR_WRONG_CAREER;
    }

    return 0;
}

int CMatrixMgr::GetMatrixObjNum(CMatrixList& stMatrixList)
{
    int iObjNum = 0;
    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        if (stMatrixList._astMatrixList[i]._chType > 0)
        {
            ++iObjNum;
        }
    }

    return iObjNum;
}

int CMatrixMgr::GetLevelLimit(int iLevel)
{
#if 0
    if (iLevel < MATRIX_LEVLE_LIMIT_LVL_A)
    {
        return MATRIX_LEVLE_LIMIT_NUM_INIT;
    }
    else if (iLevel < MATRIX_LEVLE_LIMIT_LVL_B)
    {
        return MATRIX_LEVLE_LIMIT_NUM_A;
    }

    return MATRIX_LEVLE_LIMIT_NUM_B;
#endif
    //初始可以上阵数量就是最大 不再随等级限制
    return MATRIX_LEVLE_LIMIT_NUM_B;
}

int CMatrixMgr::CheckLevelLimit(int iLevel, int iNum)
{
    if (iNum > GetLevelLimit(iLevel))
    {
        return ERROR_MATRIX_LEVEL_NUM_LIMIT;
    }

    return 0;
}

//拷贝响应包的团队战斗力以及总先攻值
void CMatrixMgr::GetMatrixFighting(CPlayerDetailInfo& stPlayerDetail,
        CPlayerOnlineData& stPlayerOnline, MsgMatrixList& stMsgMatrixList)
{
    CalcMainFighting(stPlayerDetail, stPlayerOnline);//团队战斗力

    stMsgMatrixList.set_matrix_fighting(
        CMainCtrl::m_pstMain->m_stRoleMgr.GetTeamFighting(stPlayerOnline));

    //以下计算总的先攻值
    CPlayerAttr& stRoleAttr = stPlayerOnline._stUserRole.GetAttr();
    int iTurnOrder = stRoleAttr.GetAttr(EXT_ATTR_TURN_ORDRE);

    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    if (stPlayerMatrix._chMainMatrix < 0 ||
        stPlayerMatrix._chMainMatrix >= stPlayerMatrix._astMatrixData.Size())
    {
        return;
    }

    CMatrixList& stMatrixList =
        stPlayerMatrix._astMatrixData[stPlayerMatrix._chMainMatrix];

    int iIndex = 0;
    short shPartnerID = 0;
    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        if (GAME_OBJ_TYPE_PARTNER != stMatrixList._astMatrixList[i]._chType ||
            stMatrixList._astMatrixList[i]._uiID <= 0)
        {
            continue;
        }

        shPartnerID = (short)stMatrixList._astMatrixList[i]._uiID;
        iIndex = stPlayerOnline._stUserPartner.FindPartner(shPartnerID);
        if (iIndex < 0)
        {
            CT_ERROR(("role(%u) partner(%d) not in act",stPlayerDetail._uiGID,
                      shPartnerID));
            continue;
        }

        CPartnerUnit& stPartnerUnit =
            stPlayerOnline._stUserPartner.GetPartner(iIndex);

        iTurnOrder += stPartnerUnit._stAttr.GetAttr(EXT_ATTR_TURN_ORDRE);
    }

    stMsgMatrixList.set_matrix_turn_order(iTurnOrder);
}

//主动下发阵型 当前只有登录时候下发 不要求实时下发
int CMatrixMgr::NotifyMatrix(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline)
{
    MsgAnsMatrix stMatrixAns;

    stMatrixAns.set_gid(stPlayerBase._uiGID);
    stMatrixAns.set_sub_type(CMD_MATRIX_SUB_GET);

    GetMatrixData(stPlayerBase, stPlayerDetail, stPlayerOnline, stMatrixAns);

    CMainCtrl::m_pstMain->NotifyOnlineUser(stPlayerDetail._uiGID,
        ID_MAIN_MATRIX, stMatrixAns, false);

    return 0;
}

//拉取阵形列表
int CMatrixMgr::GetMatrixData(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        MsgAnsMatrix& stAns)
{
    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    if (stPlayerMatrix._chMainMatrix < 0 ||
        stPlayerMatrix._chMainMatrix >= stPlayerMatrix._astMatrixData.Size())
    {
        CT_ERROR(("role(%u) matrix size(%d) main matrix index(%d)",
            stPlayerDetail._uiGID,stPlayerMatrix._astMatrixData.Size(),
            stPlayerMatrix._chMainMatrix));
        return 0;
    }

    stAns.set_current_matrix_idx(stPlayerMatrix._chMainMatrix);
    stAns.set_number_limit(GetLevelLimit(stPlayerBase._shLevel));

    for (int i = 0; i < stPlayerMatrix._astMatrixData.Size(); ++i)
    {
        MsgMatrixList* pstMatrixList = stAns.add_matrix_list();
        if (pstMatrixList)
        {
            CopyMatrixListToAns(stPlayerDetail, stPlayerOnline,
                stPlayerMatrix._astMatrixData[i], (*pstMatrixList));
        }
        else
        {
            CT_ERROR(("get matrix data but matrix list pointer null!"));
        }
    }

    return 0;
}

int CMatrixMgr::CopyMatrixListToAns(CPlayerDetailInfo& stPlayerDetail,
        CPlayerOnlineData& stPlayerOnline, CMatrixList& stMatrixList,
        MsgMatrixList& stMsgMatrixList)
{
    int iIndex = 0;
    int iTurnOrder = 0;

    GetMatrixFighting(stPlayerDetail, stPlayerOnline, stMsgMatrixList);

    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        if (stMatrixList._astMatrixList[i]._chType <= 0)
        {
            continue;
        }
        MsgMatrixUnit* pstMatrixUnit = stMsgMatrixList.add_matrix_units();
        if (!pstMatrixUnit)
        {
            CT_ERROR(("matrix unit pointer null!"));
            continue;
        }

        iTurnOrder = 0;

        if (GAME_OBJ_TYPE_PLAYER == stMatrixList._astMatrixList[i]._chType)
        {
            CPlayerAttr& stRoleAttr = stPlayerOnline._stUserRole.GetAttr();
            iTurnOrder = stRoleAttr.GetAttr(EXT_ATTR_TURN_ORDRE);
        }
        else if (GAME_OBJ_TYPE_PARTNER ==
                    stMatrixList._astMatrixList[i]._chType)
        {
            iIndex = stPlayerOnline._stUserPartner.FindPartner(
                (short)stMatrixList._astMatrixList[i]._uiID);
            if (iIndex >= 0)
            {
                CPartnerUnit& stPartner =
                    stPlayerOnline._stUserPartner.GetPartner(iIndex);
                CPlayerAttr& stPartnerAttr = stPartner.GetAttr();
                iTurnOrder = stPartnerAttr.GetAttr(EXT_ATTR_TURN_ORDRE);
            }
        }

        pstMatrixUnit->set_order(i+1);
        pstMatrixUnit->set_type(stMatrixList._astMatrixList[i]._chType);
        iIndex = GetPosNumByIndex(stMatrixList._astMatrixList[i]._chPos);
        pstMatrixUnit->set_pos(iIndex);
        pstMatrixUnit->set_id(stMatrixList._astMatrixList[i]._uiID);
        pstMatrixUnit->set_turn_order(iTurnOrder);
    }

    return 0;
}

bool CMatrixMgr::IsMainMatrix(CPlayerDetailInfo& stPlayerDetail, char chIndex)
{
    return (chIndex == stPlayerDetail._stPlayerMatrix._chMainMatrix);
}

//设置主阵形
int CMatrixMgr::SetMainMatrix(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        MsgReqMatrix& stReq, MsgAnsMatrix& stAns)
{
    if (!stReq.has_matrix_idx())
    {
        return RET_REQ_NOT_COMPLETE;
    }

    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    char chMain = (char)stReq.matrix_idx();

    if (chMain < 0 || chMain >= stPlayerMatrix._astMatrixData.Size())
    {
        return ERROR_MATRIX_INDEX_INVALID;
    }

    stPlayerMatrix._chMainMatrix = chMain;

    return GetMatrixData(stPlayerBase, stPlayerDetail, stPlayerOnline, stAns);
}

int CMatrixMgr::CheckObjAddMatrix(CMatrixList& stMatrixList,
        const MsgMatrixUnit& stMatrixUnit, CPlayerBaseInfo& stPlayerBase,
        CPlayerOnlineData& stPlayerOnline, unsigned int& uiPosMask, int& iOrder,
        char& chPos, char& chCareer)
{
    int iRet = 0;
    int iIndex = 0;

    iRet = CheckMatrixObjType(stMatrixUnit.type());
    CT_RETURN(iRet);

    //加入的个体类型不能是角色
    if (stMatrixUnit.type() == GAME_OBJ_TYPE_PLAYER)
    {
        return ERROR_MATRIX_ADD_ROLE_TO_SELF;
    }

    char chOldCareer = -1;
    chPos = GetIndexByPosNum(stMatrixUnit.pos());
    iRet = IndexToPosMask(uiPosMask, chPos);
    CT_RETURN(iRet);

    if ((stMatrixList._uiPosMask & uiPosMask) != 0)
    {
        iOrder = -1;

        for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
        {
            if (chPos == stMatrixList._astMatrixList[i]._chPos)
            {
                iOrder = i;
                break;
            }
        }

        if (iOrder < 0)
        {
            CT_WARNING(("pos mask(%u) obj pos mask(%u) pos(%d) order(%d)",
                stMatrixList._uiPosMask,uiPosMask,chPos,iOrder));
            return ERROR_MATRIX_REQINFO_NOT_MATCH;
        }

        CMatrixUnit& stMatrixObj = stMatrixList._astMatrixList[iOrder];

        if (GAME_OBJ_TYPE_PARTNER == stMatrixObj._chType)
        {
            short shPartnerID = (short)stMatrixObj._uiID;
            iIndex = stPlayerOnline._stUserPartner.FindPartner(shPartnerID);
            if (iIndex < 0)
            {
                CT_WARNING(("matrix obj is partner(%d) but not in act!",
                    shPartnerID));
                return ERROR_PARTNER_NOT_IN_ACT;
            }

            iIndex = CMainCtrl::m_pstMain->m_stPartnerMgr.FindPartnerCfg(
                shPartnerID);
            if (iIndex < 0)
            {
                return ERROR_PARTNER_EMPTY_CFG;
            }
            CPartnerCfgData& stPartnerCfg =
                CMainCtrl::m_pstMain->m_stPartnerMgr.GetPartnerCfg(iIndex);

            chOldCareer = stPartnerCfg.GetCareer();
        }
        else if (GAME_OBJ_TYPE_PLAYER == stMatrixObj._chType)
        {
            return ERROR_MATRIX_DEL_ROLE_FROM_SELF;
        }
    }

    //不是替换 所以需要检查等级数量限制
    if ((stMatrixList._uiPosMask & uiPosMask) == 0)
    {
        iRet = CheckLevelLimit(stPlayerBase._shLevel,
            GetMatrixObjNum(stMatrixList) + 1);
        CT_RETURN(iRet);
    }

    if (stMatrixUnit.type() == GAME_OBJ_TYPE_PARTNER)
    {
        short shPartnerID = (short)stMatrixUnit.id();
        iIndex = stPlayerOnline._stUserPartner.FindPartner(shPartnerID);
        if (iIndex < 0)
        {
            CT_WARNING(("adding matrix obj is partner(%d) but not in act!",
                shPartnerID));
            return ERROR_PARTNER_NOT_IN_ACT;
        }
        CPartnerUnit& stPartnerUnit =
            stPlayerOnline._stUserPartner.GetPartner(iIndex);

        iIndex = CMainCtrl::m_pstMain->m_stPartnerMgr.FindPartnerCfg(
            shPartnerID);
        if (iIndex < 0)
        {
            return ERROR_PARTNER_EMPTY_CFG;
        }
        CPartnerCfgData& stPartnerCfg =
            CMainCtrl::m_pstMain->m_stPartnerMgr.GetPartnerCfg(iIndex);

        chCareer = stPartnerCfg.GetCareer();

        if (chCareer != chOldCareer)
        {
            iRet = CheckCareerPos(chCareer, chPos, GAME_OBJ_TYPE_PARTNER);
            CT_RETURN(iRet);

#if 0 //策划要求暂时不限制职业数量
            int iMaxCount = 0;
            iRet = GetCareerLimit(chCareer, iMaxCount);
            CT_RETURN(iRet);

            if (stMatrixList._achCareerCount[chCareer - 1] >= iMaxCount)
            {
                return ERROR_MATRIX_CAREER_COUNT_LIMIT;
            }
#endif
        }

        //伙伴在同一阵形中不能重复
        for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
        {
            if (GAME_OBJ_TYPE_PARTNER ==
                    stMatrixList._astMatrixList[i]._chType &&
                (unsigned int)stPartnerUnit._shResID ==
                    stMatrixList._astMatrixList[i]._uiID)
            {
                return ERROR_MATRIX_PARTNER_ALREADY;
            }
        }
    }

    return 0;
}

//加入个体 当前逻辑为角色加个体到自身阵形中 不能加角色(包括自己)
int CMatrixMgr::AddToMatrix(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        MsgReqMatrix& stReq, MsgAnsMatrix& stAns)
{
    int iRet = 0;
    if (!stReq.has_matrix_idx() || stReq.unit_datas_size() <= 0)
    {
        return RET_REQ_NOT_COMPLETE;
    }

    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    //检查目标阵形是否存在
    char chMatrixIndex =(char)stReq.matrix_idx();
    if (chMatrixIndex < 0 ||
        chMatrixIndex >= stPlayerMatrix._astMatrixData.Size())
    {
        return ERROR_MATRIX_INDEX_INVALID;
    }

    const MsgMatrixUnit& stReqUnit = stReq.unit_datas(0);

    iRet = CheckMatrixObjType(stReqUnit.type());
    CT_RETURN(iRet);

    //加入的个体类型不能是角色
    if (stReqUnit.type() == GAME_OBJ_TYPE_PLAYER)
    {
        return ERROR_MATRIX_ADD_ROLE_TO_SELF;
    }

    CMatrixList& stMatrixList = stPlayerMatrix._astMatrixData[chMatrixIndex];

    char chPos = 0;
    char chCareer = -1;
    int iUnitIndex = -1;
    unsigned int uiPosMask = 0;

    iRet = CheckObjAddMatrix(stMatrixList, stReqUnit, stPlayerBase,
        stPlayerOnline, uiPosMask, iUnitIndex, chPos, chCareer);
    CT_RETURN(iRet);

    if ((stMatrixList._uiPosMask & uiPosMask) != 0)
    {
        if (iUnitIndex < 0 || iUnitIndex >= stMatrixList._astMatrixList.Size())
        {
            return ERROR_MATRIX_REQINFO_NOT_MATCH;
        }

        MsgReqMatrix stReqTmp;
        MsgAnsMatrix stAnsTmp;
        stReqTmp.set_matrix_idx(chMatrixIndex);
        MsgMatrixUnit* pstMatrixUnit = stReqTmp.add_unit_datas();
        if (!pstMatrixUnit)
        {
            return RET_SYS_NULL_POINTER;
        }

        pstMatrixUnit->set_order(0);//可以设置为optional
        pstMatrixUnit->set_type(
            stMatrixList._astMatrixList[iUnitIndex]._chType);
        pstMatrixUnit->set_pos(0);
        pstMatrixUnit->set_id(
            (int)stMatrixList._astMatrixList[iUnitIndex]._uiID);

        iRet = DelFromMatrix(stPlayerBase, stPlayerDetail, stPlayerOnline,
            stReqTmp, stAnsTmp, false);
        CT_RETURN(iRet);
    }

    if (iUnitIndex < 0)
    {
        //从较高出手顺序(值小)找一个空的给新加入
        for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
        {
            if (stMatrixList._astMatrixList[i]._chType == 0)
            {
                iUnitIndex = i;
                break;
            }
        }

        if (iUnitIndex < 0)
        {
            return ERROR_MATRIX_OBJ_FULL_ALREADY;
        }
    }

    if (stReqUnit.type() == GAME_OBJ_TYPE_PARTNER)
    {
        if (chCareer < 0 || chCareer > CAREER_END)
        {
            CT_ERROR(("matrix obj is partner(%d) but career(%d) error",
                stReqUnit.id(),chCareer));
            return ERROR_MATRIX_REQINFO_NOT_MATCH;
        }

        //替换式加入个体 后移以保证出手顺位
        for (int i = stMatrixList._astMatrixList.Size() - 1; i > iUnitIndex;
                --i)
        {
            if (i - 1 >= 0 && stMatrixList._astMatrixList[i - 1]._chType > 0)
            {
                stMatrixList._astMatrixList[i] =
                    stMatrixList._astMatrixList[i - 1];
            }
        }

        stMatrixList._uiPosMask |= uiPosMask;
        ++stMatrixList._achCareerCount[chCareer - 1];

        stMatrixList._astMatrixList[iUnitIndex]._chType = GAME_OBJ_TYPE_PARTNER;
        stMatrixList._astMatrixList[iUnitIndex]._chPos = chPos;
        stMatrixList._astMatrixList[iUnitIndex]._uiID =
            (unsigned int)stReqUnit.id();
    }

    return GetMatrixData(stPlayerBase, stPlayerDetail, stPlayerOnline, stAns);
}

//移出个体 当前逻辑为角色从自身阵形移出个体 不能移出角色(包括自己)
int CMatrixMgr::DelFromMatrix(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        MsgReqMatrix& stReq, MsgAnsMatrix& stAns, bool bNeedCopyData)
{
    int iRet = 0;
    int iIndex = 0;
    if (!stReq.has_matrix_idx() || stReq.unit_datas_size() <= 0)
    {
        return RET_REQ_NOT_COMPLETE;
    }

    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    //检查目标阵形是否存在
    char chMatrixIndex = (char)stReq.matrix_idx();
    if (chMatrixIndex < 0 ||
        chMatrixIndex >= stPlayerMatrix._astMatrixData.Size())
    {
        return ERROR_MATRIX_INDEX_INVALID;
    }

    const MsgMatrixUnit& stReqUnit = stReq.unit_datas(0);

    iRet = CheckMatrixObjType(stReqUnit.type());
    CT_RETURN(iRet);

    //移出的个体类型不能是角色
    if (stReqUnit.type() == GAME_OBJ_TYPE_PLAYER)
    {
        return ERROR_MATRIX_DEL_ROLE_FROM_SELF;
    }

    CMatrixList& stMatrixList = stPlayerMatrix._astMatrixData[chMatrixIndex];

    int iUnitIndex = GetUnitIndexByTypeAndID(stMatrixList, stReqUnit.type(),
            (unsigned int)stReqUnit.id());
    CT_CHECK(iUnitIndex, ERROR_MATRIX_REQINFO_NOT_MATCH);

    unsigned int uiPosMask = 0;
    iRet = IndexToPosMask(uiPosMask,
        stMatrixList._astMatrixList[iUnitIndex]._chPos);
    CT_RETURN(iRet);

    if (stReqUnit.type() == GAME_OBJ_TYPE_PARTNER)
    {
        iIndex = CMainCtrl::m_pstMain->m_stPartnerMgr.FindPartnerCfg(
            (short)stReqUnit.id());
        if (iIndex < 0)
        {
            return ERROR_PARTNER_EMPTY_CFG;
        }
        CPartnerCfgData& stPartnerCfg =
            CMainCtrl::m_pstMain->m_stPartnerMgr.GetPartnerCfg(iIndex);

        //仅仅是为了校验职业配置值是否合法 因为职业减一作为下标
        iRet = CheckCareerPos(stPartnerCfg.GetCareer(),
            stMatrixList._astMatrixList[iUnitIndex]._chPos,
            GAME_OBJ_TYPE_PARTNER);
        CT_RETURN(iRet);

        //清掉站位掩码
        stMatrixList._uiPosMask &= (~uiPosMask);
        --stMatrixList._achCareerCount[stPartnerCfg.GetCareer() - 1];

        //清掉个体信息
        for (int i = iUnitIndex; i < stMatrixList._astMatrixList.Size() - 1;
                ++i)
        {
            stMatrixList._astMatrixList[i] = stMatrixList._astMatrixList[i + 1];
        }

        int iLastUnitIndex = stMatrixList._astMatrixList.Size() - 1;
        stMatrixList._astMatrixList[iLastUnitIndex]._chType = 0;
        stMatrixList._astMatrixList[iLastUnitIndex]._chPos = 0;
        stMatrixList._astMatrixList[iLastUnitIndex]._uiID = 0;
    }

    if (bNeedCopyData)
    {
        return GetMatrixData(stPlayerBase, stPlayerDetail, stPlayerOnline,
            stAns);
    }

    return 0;
}

int CMatrixMgr::GetMatrixCareer(unsigned char& ucCareer,
        CMatrixUnit& stMatrixUnit)
{
    int iRet = 0;
    int iIndex = 0;
    if (GAME_OBJ_TYPE_PLAYER == stMatrixUnit._chType)
    {
        iIndex = CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash.HashFind(
            stMatrixUnit._uiID);
        if (iIndex < 0)
        {
            return RET_NOT_LOGIN;
        }
        CPlayerBaseInfo& stPlayerBase =
            CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash[iIndex];

        //仅仅是为了校验职业配置值是否合法
        iRet = CheckCareerPos(stPlayerBase._ucCareer, stMatrixUnit._chPos,
            GAME_OBJ_TYPE_PLAYER);
        CT_RETURN(iRet);

        ucCareer = stPlayerBase._ucCareer;
    }
    else if (GAME_OBJ_TYPE_PARTNER  == stMatrixUnit._chType)
    {
        iIndex = CMainCtrl::m_pstMain->m_stPartnerMgr.FindPartnerCfg(
            (short)stMatrixUnit._uiID);
        if (iIndex < 0)
        {
            return ERROR_PARTNER_EMPTY_CFG;
        }
        CPartnerCfgData& stPartnerCfg =
            CMainCtrl::m_pstMain->m_stPartnerMgr.GetPartnerCfg(iIndex);

        //仅仅是为了校验职业配置值是否合法
        iRet = CheckCareerPos(stPartnerCfg.GetCareer(), stMatrixUnit._chPos,
            GAME_OBJ_TYPE_PARTNER);
        CT_RETURN(iRet);

        ucCareer = (unsigned char)stPartnerCfg.GetCareer();
    }
    else
    {
        return ERROR_MATRIX_UNKNOWN_OBJ_TYPE;
    }

    return 0;
}

//交换两个个体
int CMatrixMgr::SwapTwoMatrix(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        MsgReqMatrix& stReq, MsgAnsMatrix& stAns)
{
    if (!stReq.has_matrix_idx() || stReq.unit_datas_size() < 2)
    {
        //请求包携带交换的两个个体信息
        return RET_REQ_NOT_COMPLETE;
    }

    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    //检查目标阵形是否存在
    if (stReq.matrix_idx() < 0 ||
        stReq.matrix_idx() >= stPlayerMatrix._astMatrixData.Size())
    {
        return ERROR_MATRIX_INDEX_INVALID;
    }

    const MsgMatrixUnit& stReqUnitA = stReq.unit_datas(0);
    const MsgMatrixUnit& stReqUnitB = stReq.unit_datas(1);

    int iRet = 0;
    unsigned int uiPosMaskA = 0;
    unsigned int uiPosMaskB = 0;
    char chPosA = GetIndexByPosNum(stReqUnitA.pos());
    char chPosB = GetIndexByPosNum(stReqUnitB.pos());

    iRet = IndexToPosMask(uiPosMaskA, chPosA);
    CT_RETURN(iRet);
    iRet = IndexToPosMask(uiPosMaskB, chPosB);
    CT_RETURN(iRet);

    if (uiPosMaskA == uiPosMaskB)
    {
        return ERROR_MATRIX_TWO_POS_INDEX_SAME;
    }

    CMatrixList& stMatrixList =
        stPlayerMatrix._astMatrixData[stReq.matrix_idx()];

    if ((stMatrixList._uiPosMask & uiPosMaskA) == 0 &&
        (stMatrixList._uiPosMask & uiPosMaskB) == 0)
    {
        //不能交换两个空的个体
        return ERROR_MATRIX_SWAP_TWO_EMPTY_OBJ;
    }

    unsigned char ucCareerA = 0;
    unsigned char ucCareerB = 0;

    //A、B都是存在的个体
    if ((stMatrixList._uiPosMask & uiPosMaskA) != 0 &&
        (stMatrixList._uiPosMask & uiPosMaskB) != 0)
    {
        int iUnitIndexA = GetUnitIndexByTypeAndID(stMatrixList,
                stReqUnitA.type(), (unsigned int)stReqUnitA.id());
        CT_CHECK(iUnitIndexA, ERROR_MATRIX_REQINFO_NOT_MATCH);

        int iUnitIndexB = GetUnitIndexByTypeAndID(stMatrixList,
                stReqUnitB.type(), (unsigned int)stReqUnitB.id());
        CT_CHECK(iUnitIndexB, ERROR_MATRIX_REQINFO_NOT_MATCH);

        iRet = GetMatrixCareer(ucCareerA,
            stMatrixList._astMatrixList[iUnitIndexA]);
        CT_RETURN(iRet);

        iRet = GetMatrixCareer(ucCareerB,
            stMatrixList._astMatrixList[iUnitIndexB]);
        CT_RETURN(iRet);

        iRet = CheckCareerPos(ucCareerA, chPosB,
            stMatrixList._astMatrixList[iUnitIndexA]._chType);
        CT_RETURN(iRet);

        iRet = CheckCareerPos(ucCareerB, chPosA,
            stMatrixList._astMatrixList[iUnitIndexB]._chType);
        CT_RETURN(iRet);

        char chPosTmp  = stMatrixList._astMatrixList[iUnitIndexA]._chPos;
        stMatrixList._astMatrixList[iUnitIndexA]._chPos =
            stMatrixList._astMatrixList[iUnitIndexB]._chPos;
        stMatrixList._astMatrixList[iUnitIndexB]._chPos = chPosTmp;
    }
    //A个体空，B个体存在
    else if ((stMatrixList._uiPosMask & uiPosMaskA) == 0 &&
                (stMatrixList._uiPosMask & uiPosMaskB) != 0)
    {
        int iUnitIndexB = GetUnitIndexByTypeAndID(stMatrixList,
                stReqUnitB.type(), (unsigned int)stReqUnitB.id());
        CT_CHECK(iUnitIndexB, ERROR_MATRIX_REQINFO_NOT_MATCH);

        iRet = GetMatrixCareer(ucCareerB,
            stMatrixList._astMatrixList[iUnitIndexB]);
        CT_RETURN(iRet);

        iRet = CheckCareerPos(ucCareerB, chPosA,
            stMatrixList._astMatrixList[iUnitIndexB]._chType);
        CT_RETURN(iRet);

        //清掉B站位掩码
        stMatrixList._uiPosMask &= (~uiPosMaskB);
        //置上A站位掩码
        stMatrixList._uiPosMask |= uiPosMaskA;
        //将个体B赋值为A站位
        stMatrixList._astMatrixList[iUnitIndexB]._chPos = chPosA;
    }
    //A个体存在，B个体空
    else if ((stMatrixList._uiPosMask & uiPosMaskA) != 0 &&
                (stMatrixList._uiPosMask & uiPosMaskB) == 0)
    {
        int iUnitIndexA = GetUnitIndexByTypeAndID(stMatrixList,
                stReqUnitA.type(), (unsigned int)stReqUnitA.id());
        CT_CHECK(iUnitIndexA, ERROR_MATRIX_REQINFO_NOT_MATCH);

        iRet = GetMatrixCareer(ucCareerA,
            stMatrixList._astMatrixList[iUnitIndexA]);
        CT_RETURN(iRet);

        iRet = CheckCareerPos(ucCareerA, chPosB,
            stMatrixList._astMatrixList[iUnitIndexA]._chType);
        CT_RETURN(iRet);

        //清掉A站位掩码
        stMatrixList._uiPosMask &= (~uiPosMaskA);
        //置上B站位掩码
        stMatrixList._uiPosMask |= uiPosMaskB;
        //将个体A赋值为B站位
        stMatrixList._astMatrixList[iUnitIndexA]._chPos = chPosB;
    }

    return GetMatrixData(stPlayerBase, stPlayerDetail, stPlayerOnline, stAns);
}

//交换两个出手顺序
int CMatrixMgr::SwapTwoOrder(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        MsgReqMatrix& stReq, MsgAnsMatrix& stAns)
{
    int iRet = 0;
    if (!stReq.has_matrix_idx() || stReq.unit_datas_size() < 2)
    {
        //请求包携带交换的两个出手顺序
        return RET_REQ_NOT_COMPLETE;
    }

    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    //检查目标阵形是否存在
    if (stReq.matrix_idx() < 0 ||
        stReq.matrix_idx() >= stPlayerMatrix._astMatrixData.Size())
    {
        return ERROR_MATRIX_INDEX_INVALID;
    }

    const MsgMatrixUnit& stReqUnitA = stReq.unit_datas(0);
    const MsgMatrixUnit& stReqUnitB = stReq.unit_datas(1);

    iRet = CheckMatrixObjType(stReqUnitA.type());
    CT_RETURN(iRet);

    iRet = CheckMatrixObjType(stReqUnitB.type());
    CT_RETURN(iRet);

    CMatrixList& stMatrixList =
        stPlayerMatrix._astMatrixData[stReq.matrix_idx()];

    int iUnitIndexA = GetUnitIndexByTypeAndID(stMatrixList, stReqUnitA.type(),
            (unsigned int)stReqUnitA.id());
    CT_CHECK(iUnitIndexA, ERROR_MATRIX_REQINFO_NOT_MATCH);

    int iUnitIndexB = GetUnitIndexByTypeAndID(stMatrixList, stReqUnitB.type(),
            (unsigned int)stReqUnitB.id());
    CT_CHECK(iUnitIndexB, ERROR_MATRIX_REQINFO_NOT_MATCH);

    if (iUnitIndexA == iUnitIndexB)
    {
        return ERROR_MATRIX_TWO_POS_INDEX_SAME;
    }

    CMatrixUnit stUnitTmp = stMatrixList._astMatrixList[iUnitIndexA];
    stMatrixList._astMatrixList[iUnitIndexA] =
        stMatrixList._astMatrixList[iUnitIndexB];
    stMatrixList._astMatrixList[iUnitIndexB] = stUnitTmp;

    return GetMatrixData(stPlayerBase, stPlayerDetail, stPlayerOnline, stAns);
}

//伙伴离队清掉阵形中所有该伙伴信息
int CMatrixMgr::DelAllPartner(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        short shResID)
{
    int iRet = 0;
    int iIndex = 0;
    unsigned int uiPosMask = 0;
    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    iIndex = CMainCtrl::m_pstMain->m_stPartnerMgr.FindPartnerCfg(shResID);
    if (iIndex < 0)
    {
        return ERROR_PARTNER_EMPTY_CFG;
    }
    CPartnerCfgData& stPartnerCfg =
        CMainCtrl::m_pstMain->m_stPartnerMgr.GetPartnerCfg(iIndex);

    int iTmp;
    char chCareer = stPartnerCfg.GetCareer();
    iRet = GetCareerLimit(chCareer, iTmp); //仅仅是为了校验职业配置值是否合法
    CT_RETURN(iRet);

    //构造拉取阵形列表的应答包 用于前台刷新阵形
    bool bNotify = false;

    for (int i = 0; i < stPlayerMatrix._astMatrixData.Size(); ++i)
    {
        CMatrixList& stMatrixList = stPlayerMatrix._astMatrixData[i];
        for (int j = 0; j < stMatrixList._astMatrixList.Size(); ++j)
        {
            if (GAME_OBJ_TYPE_PARTNER == stMatrixList._astMatrixList[j]._chType &&
                (unsigned int)shResID == stMatrixList._astMatrixList[j]._uiID)
            {
                iRet = IndexToPosMask(uiPosMask,
                    stMatrixList._astMatrixList[j]._chPos);
                if (iRet){continue;}//低概率事件 只为保护_uiPosMask 

                //清掉站位掩码
                stMatrixList._uiPosMask &= (~uiPosMask);
                --stMatrixList._achCareerCount[chCareer - 1];

                //清掉个体信息
                for (iIndex = j;
                        iIndex < stMatrixList._astMatrixList.Size() - 1;
                            ++iIndex)
                {
                    stMatrixList._astMatrixList[iIndex] =
                        stMatrixList._astMatrixList[iIndex + 1];
                }

                iIndex = stMatrixList._astMatrixList.Size() - 1;
                stMatrixList._astMatrixList[iIndex]._chType = 0;
                stMatrixList._astMatrixList[iIndex]._chPos = 0;
                stMatrixList._astMatrixList[iIndex]._uiID = 0;

                bNotify = true;

                break;
            }
        }
    }

    if (bNotify)
    {
        MsgAnsMatrix stMsgAnsMatrix;
        stMsgAnsMatrix.set_gid((int)stPlayerDetail._uiGID);
        stMsgAnsMatrix.set_sub_type(CMD_MATRIX_SUB_GET);

        iRet = GetMatrixData(stPlayerBase, stPlayerDetail, stPlayerOnline,
            stMsgAnsMatrix);
        if (!iRet)
        {
            CMainCtrl::m_pstMain->NotifyOnlineUser(stPlayerDetail._uiGID,
                ID_MAIN_MATRIX, stMsgAnsMatrix, false);
        }
    }

    return 0;
}

bool CMatrixMgr::PartnerInMainMatrix(CPlayerDetailInfo& stPlayerDetail,
        short shResID)
{
    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    if (stPlayerMatrix._chMainMatrix < 0 ||
        stPlayerMatrix._chMainMatrix >= stPlayerMatrix._astMatrixData.Size())
    {
        return false;
    }

    CMatrixList& stMatrixList =
        stPlayerMatrix._astMatrixData[stPlayerMatrix._chMainMatrix];
    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        if (GAME_OBJ_TYPE_PARTNER == stMatrixList._astMatrixList[i]._chType &&
            (unsigned int)shResID == stMatrixList._astMatrixList[i]._uiID)
        {
            return true;
        }
    }

    return false;
}

void CMatrixMgr::SendMatrixFightingToFront(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline)
{
    int iRet = 0;
    MsgAnsMatrix stAns;
    stAns.set_gid((int)stPlayerDetail._uiGID);
    stAns.set_sub_type(CMD_MATRIX_SUB_GET);

    iRet = GetMatrixData(stPlayerBase, stPlayerDetail, stPlayerOnline, stAns);
    if (iRet)
    {
        CT_ERROR(("send fighting to front but get matrix data error(%d)",iRet));
        return;
    }

    CMainCtrl::m_pstMain->NotifyOnlineUser(stPlayerDetail._uiGID,
        ID_MAIN_MATRIX, stAns, false);
}

//触发重新计算团队战斗力不重新更新各个个体战斗力
int CMatrixMgr::CalcMainFighting(CPlayerDetailInfo& stPlayerDetail,
        CPlayerOnlineData& stPlayerOnline)
{
    int iIndex = 0;
    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    if (stPlayerMatrix._chMainMatrix < 0 ||
        stPlayerMatrix._chMainMatrix >= stPlayerMatrix._astMatrixData.Size())
    {
        CT_ERROR(("matrix size(%d) main matrix index(%d)",
                  stPlayerMatrix._astMatrixData.Size(),
                  stPlayerMatrix._chMainMatrix));
        return 0;
    }

    //这里是团队战斗力计算的起点
    stPlayerOnline._iTeamFighting = 0;

    CMatrixList& stMatrixList =
        stPlayerMatrix._astMatrixData[stPlayerMatrix._chMainMatrix];

    short shPartnerID = 0;
    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        if (GAME_OBJ_TYPE_PARTNER != stMatrixList._astMatrixList[i]._chType ||
            stMatrixList._astMatrixList[i]._uiID <= 0)
        {
            continue;
        }

        shPartnerID = (short)stMatrixList._astMatrixList[i]._uiID;

        iIndex = stPlayerOnline._stUserPartner.FindPartner(shPartnerID);
        if (iIndex >= 0)
        {
            CPartnerUnit& stPartnerUnit =
                stPlayerOnline._stUserPartner.GetPartner(iIndex);

            stPlayerOnline._iTeamFighting += stPartnerUnit.GetFighting();
        }
        else
        {
            CT_ERROR(("role(%u) partner(%d) no online data",
                      stPlayerDetail._uiGID, shPartnerID));
        }
    }

    stPlayerDetail._stBattleFightingHis.AddHis(
        CMainCtrl::m_pstMain->m_stRoleMgr.GetTeamFighting(stPlayerOnline),
            CMainCtrl::m_pstMain->m_iNow);

    CMainCtrl::m_pstMain->m_stRoleMgr.UpdateFightingInSns(stPlayerOnline);

    return 0;
}

//重新计算阵形上每个个体的战斗力并更新到个体属性上而且下发前端
int CMatrixMgr::ReCalcMainFighting(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline)
{
    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    if (stPlayerMatrix._chMainMatrix < 0 ||
        stPlayerMatrix._chMainMatrix >= stPlayerMatrix._astMatrixData.Size())
    {
        CT_ERROR(("matrix size(%d) main matrix index(%d)",
                  stPlayerMatrix._astMatrixData.Size(),
                  stPlayerMatrix._chMainMatrix));
        return 0;
    }

    //这里是团队战斗力计算的起点
    stPlayerOnline._iTeamFighting = 0;

    //重新计算主角的个体战斗力
    CMainCtrl::m_pstMain->m_stRoleMgr.CalcObjFighting(stPlayerDetail._uiGID,
        GAME_OBJ_TYPE_PLAYER, 0);

    //下发用户属性
    CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stPlayerDetail._uiGID,
        NOTIFY_ROLE_INFO);

    for (int i = 0; i < stPlayerDetail._stUserPartner._astActData.Size(); ++i)
    {
        CPartnerActData& stActData =
            stPlayerDetail._stUserPartner._astActData[i];

        //重新计算所有伙伴个体战斗力
        CMainCtrl::m_pstMain->m_stRoleMgr.CalcObjFighting(stPlayerDetail._uiGID,
            GAME_OBJ_TYPE_PARTNER, stActData._shResID);

        CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stPlayerDetail._uiGID,
            NOTIFY_PARTNER_INFO, stActData._shResID);
    }

    //推阵型战斗力给前台
    SendMatrixFightingToFront(stPlayerBase, stPlayerDetail, stPlayerOnline);

    return 0;
}

int CMatrixMgr::ReCalcMainObjAttr(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        CPlayerDetailInfoEx1& stPlayerDetailEx1)
{
    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    if (stPlayerMatrix._chMainMatrix < 0 ||
        stPlayerMatrix._chMainMatrix >= stPlayerMatrix._astMatrixData.Size())
    {
        CT_ERROR(("matrix size(%d) main matrix index(%d)",
                  stPlayerMatrix._astMatrixData.Size(),
                  stPlayerMatrix._chMainMatrix));
        return 0;
    }

    //重新计算主角属性 这里暂时不建议使用notify命令下发 担心是立即使用型 不能等异步命令
    CMainCtrl::m_pstMain->m_stRoleMgr.ReCalcRoleExtAttr(stPlayerBase,
        stPlayerDetail, stPlayerOnline, stPlayerDetailEx1, true);

    CMatrixList& stMatrixList =
        stPlayerMatrix._astMatrixData[stPlayerMatrix._chMainMatrix];

    short shPartnerID = 0;
    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        if (GAME_OBJ_TYPE_PARTNER != stMatrixList._astMatrixList[i]._chType ||
            stMatrixList._astMatrixList[i]._uiID <= 0)
        {
            continue;
        }

        shPartnerID = (short)stMatrixList._astMatrixList[i]._uiID;

        //重新计算阵型伙伴属性
        stPlayerOnline._stUserPartner.ReCalcExtAttr(shPartnerID, stPlayerBase,
            stPlayerDetail, stPlayerOnline, stPlayerDetailEx1, true, false);
    }

    //推阵型战斗力给前台
    SendMatrixFightingToFront(stPlayerBase, stPlayerDetail, stPlayerOnline);

    return 0;
}

int CMatrixMgr::GetPlayerPosAndOrder(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, char& chPos, char& chOrder)
{
    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    if (stPlayerMatrix._chMainMatrix < 0 ||
        stPlayerMatrix._chMainMatrix >= stPlayerMatrix._astMatrixData.Size())
    {
        return ERROR_MATRIX_INDEX_INVALID;
    }

    CMatrixList& stMatrixList =
        stPlayerMatrix._astMatrixData[stPlayerMatrix._chMainMatrix];

    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        if (GAME_OBJ_TYPE_PLAYER == stMatrixList._astMatrixList[i]._chType &&
            stPlayerBase._uiGID == stMatrixList._astMatrixList[i]._uiID)
        {
            chPos = stMatrixList._astMatrixList[i]._chPos;
            chOrder = i;//出手顺序后台从0开始
            return 0;
        }
    }

    return ERROR_MATRIX_NO_PLAYER_INFO;
}

int CMatrixMgr::GetMatrixPos(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, char chObjType, unsigned int uiID)
{
    if (CheckMatrixObjType(chObjType))
    {
        CT_ERROR(("unknow matrix obj type(%d)!",chObjType));
        return -1;
    }

    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    if (stPlayerMatrix._chMainMatrix < 0 ||
        stPlayerMatrix._chMainMatrix >= stPlayerMatrix._astMatrixData.Size())
    {
        CT_ERROR(("role(%u) main matrix index error(%d)",stPlayerBase._uiGID,
            stPlayerMatrix._chMainMatrix));
        return -1;
    }

    CMatrixList& stMatrixList =
        stPlayerMatrix._astMatrixData[stPlayerMatrix._chMainMatrix];

    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        if (chObjType == stMatrixList._astMatrixList[i]._chType &&
            uiID == stMatrixList._astMatrixList[i]._uiID)
        {
            return GetPosNumByIndex(stMatrixList._astMatrixList[i]._chPos);
        }
    }

    return -1;
}

int CMatrixMgr::GetMatrixRtoLPos(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, char chObjType, unsigned int uiID)
{
    if (CheckMatrixObjType(chObjType))
    {
        CT_ERROR(("unknow matrix obj type(%d)!",chObjType));
        return -1;
    }

    CPlayerMatrix& stPlayerMatrix = stPlayerDetail._stPlayerMatrix;

    if (stPlayerMatrix._chMainMatrix < 0 ||
        stPlayerMatrix._chMainMatrix >= stPlayerMatrix._astMatrixData.Size())
    {
        return -1;
    }

    CMatrixList& stMatrixList =
        stPlayerMatrix._astMatrixData[stPlayerMatrix._chMainMatrix];

    for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
    {
        if (chObjType == stMatrixList._astMatrixList[i]._chType &&
            uiID == stMatrixList._astMatrixList[i]._uiID)
        {
            return GetRtoLPosNumByIndex(stMatrixList._astMatrixList[i]._chPos);
        }
    }

    return -1;
}

int CMatrixMgr::GMDealMatrix(CPlayerDetailInfo& stPlayerDetail,
        MsgReqGMPlayer& stReq, MsgAnsGMPlayer& stAns)
{
    int iIndex = stPlayerDetail._stPlayerMatrix._chMainMatrix;

    if (iIndex < 0 ||
        iIndex >= stPlayerDetail._stPlayerMatrix._astMatrixData.Size())
    {
        return ERROR_MATRIX_INDEX_INVALID;
    }

    CMatrixList& stMatrixList =
        stPlayerDetail._stPlayerMatrix._astMatrixData[iIndex];

    CTSizeString<MAX_BATTLE_NAME_BUFF> szNameStr;

    switch (stReq.sub_type())
    {
    case ID_GM_PLAYER_SUB_GET_MATRIX:
        szNameStr.Cat("主阵形列表: ");
        szNameStr.Cat("站位掩码:%u ",stMatrixList._uiPosMask);
        szNameStr.Cat("职业总数:%d ",stMatrixList._achCareerCount.Size());
        for (int i = 0; i < stMatrixList._achCareerCount.Size(); ++i)
        {
            szNameStr.Cat("职业%d:数量%d ",i+1,stMatrixList._achCareerCount[i]);
        }
        szNameStr.Cat("\n阵型个体总数:%d",stMatrixList._astMatrixList.Size());
        for (int i = 0; i < stMatrixList._astMatrixList.Size(); ++i)
        {
            szNameStr.Cat("\n类型:%d ",stMatrixList._astMatrixList[i]._chType);
            szNameStr.Cat("后端站位:%d ",stMatrixList._astMatrixList[i]._chPos);
            szNameStr.Cat("前端站位:%d ",
                GetPosNumByIndex(stMatrixList._astMatrixList[i]._chPos));
            szNameStr.Cat("ID:%u",stMatrixList._astMatrixList[i]._uiID);
        }
        stAns.set_name(szNameStr.Get());
        break;
    default:
        return ERROR_MAIN_SUB_CMD;
    }

    return 0;
}

int CMatrixMgr::CheckValidPos(T_BATTLE_SIDE_DATA& aiMonsterPos)
{
    for (int i = 0; i < aiMonsterPos.Size(); ++i)
    {
        if (aiMonsterPos[i] < 0 || aiMonsterPos[i] >= MAX_BATTLE_GRIDS_PER_SIDE)
        {
            return ERROR_MONSTER_BATTLE_POS_OVER;
        }
    }

    return 0;
}

int CMatrixMgr::CheckValidOrder(T_BATTLE_SIDE_DATA& aiMonsterOrder)
{
    int iTmpMask = 0;
    int iOrderMask = 0;
    for (int i = 0; i < aiMonsterOrder.Size(); ++i)
    {
        if (aiMonsterOrder[i] <= 0 ||
            aiMonsterOrder[i] > MAX_BATTLE_GRIDS_PER_SIDE)
        {
            return ERROR_MONSTER_BATTLE_ORDER_OVER;
        }

        iTmpMask = (0x1 << aiMonsterOrder[i]);
        if (iOrderMask & iTmpMask)
        {
            return ERROR_MONSTER_BATTLE_ORDER_REPEAT;
        }
        iOrderMask |= iTmpMask;
    }

    return 0;
}

